package com.province.platform.common.exception;

import com.province.platform.common.spi.ErrorCode;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;

public class PlatformException extends RuntimeException{
    private static final long serialVersionUID = 7064423935101822341L;

    private ErrorCode errorCode;

    public PlatformException(ErrorCode errorCode, String errorMessage) {
        super(errorCode.toString() + "-" + errorMessage);
        this.errorCode = errorCode;
    }

    public PlatformException(String errorMessage) {
        super(errorMessage);
    }

    public static PlatformException asPlatformException(String errorMessage) {
        return new PlatformException(errorMessage);
    }

    public static PlatformException asPlatformException(ErrorCode errorCode, String errorMessage) {
        return new PlatformException(errorCode, errorMessage);
    }

    public static PlatformException asPlatformException(ErrorCode errorCode, String errorMessage, Throwable cause) {
        if (cause instanceof PlatformException) {
            return (PlatformException) cause;
        }

        return new PlatformException(errorCode, errorMessage, cause);
    }

    public static PlatformException asPlatformException(ErrorCode errorCode, Throwable cause) {
        if (cause instanceof PlatformException) {
            return (PlatformException) cause;
        }

        return new PlatformException(errorCode, getMessage(cause), cause);
    }

    private PlatformException(ErrorCode errorCode, String errorMessage, Throwable cause) {
        super(errorCode.toString() + " - " + errorMessage + " - " + getMessage(cause), cause);

        this.errorCode = errorCode;
    }

    private static String getMessage(Object obj) {
        if (Objects.isNull(obj)) {
            return "";
        }

        if (obj instanceof Throwable) {
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
            ((Throwable) obj).printStackTrace(printWriter);
            return stringWriter.toString();
        } else {
            return obj.toString();
        }
    }
}
